package com.only4play.session.local;

import com.only4play.auth.AuthenticatedUser;
import com.only4play.auth.ExpirationPolicy;
import com.only4play.session.TicketGrantingTicketManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author liyuncong
 * @version 1.0
 * @file LocalTicketGrantingTicketManager
 * @brief 本地登录凭证管理
 * @details 本地登录凭证管理
 * @date 2023-11-18
 *
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                     NAME               DESCRIPTION
 * 2023-11-18               liyuncong          Created
 */
@Slf4j
@Component
public class LocalTicketGrantingTicketManager implements TicketGrantingTicketManager, ExpirationPolicy {

//    @Value("${sso.timeout}")
    private int timeout = 600;

    private Map<String, DummyTgt> tgtMap = new ConcurrentHashMap<>();


    @Override
    public void create(String tgt, AuthenticatedUser<Void> authenticatedUser) {
        long expired = Instant.now().plusSeconds(getExpiresIn()).toEpochMilli();
        tgtMap.put(tgt, new DummyTgt(authenticatedUser, expired));
        log.info("success generate tgt: {}", tgt);
    }

    @Override
    public AuthenticatedUser<Void> getAndRefresh(String tgt) {
        DummyTgt dummyTgt = tgtMap.getOrDefault(tgt, null);
        Instant now = Instant.now();
        if (Objects.isNull(dummyTgt) || now.isAfter(Instant.ofEpochMilli(dummyTgt.expired))) {
            return null;
        }
        dummyTgt.expired = now.plusSeconds(getExpiresIn()).toEpochMilli();
        return dummyTgt.authenticatedUser;
    }

    @Override
    public void set(String tgt, AuthenticatedUser<Void> authenticatedUser) {
        DummyTgt dummyTgt = tgtMap.getOrDefault(tgt, null);
        if (Objects.nonNull(dummyTgt)) {
            dummyTgt.authenticatedUser = authenticatedUser;
        }
    }

    @Override
    public void remove(String tgt) {
        tgtMap.remove(tgt);
    }

    @Override
    public int getExpiresIn() {
        return timeout;
    }

    @Scheduled(cron = SCHEDULED_CORN)
    @Override
    public void verifyExpired() {
        tgtMap.forEach((tgt, dummyTgt) -> {
            if (Instant.now().isAfter(Instant.ofEpochMilli(dummyTgt.expired))) {
                tgtMap.remove(tgt);
                log.info("tgt expired, tgt: {}", tgt);
            }
        });
    }

    private static class DummyTgt {
        private AuthenticatedUser<Void> authenticatedUser;
        private long expired;

        public DummyTgt(AuthenticatedUser<Void> authenticatedUser, long expired) {
            this.authenticatedUser = authenticatedUser;
            this.expired = expired;
        }
    }

}
